/*
 * Class Game:
 * 
 * This is the board manager for the Othello game.  It controls how a player takes a turn,
 * and keeps track of the score of the game.  It is used in Client, the GUI.
 */

/**
 *
 * @author Jill Greczek, Julio Montero, Brandon Jarratt
 */
public class Game 
{
	/** The board state, used for display */
	private Player[][] boardState;
	
	/** The AI that will make decisions for the computer player. */
	private team2_AI AI;
	
	/** These private variables keep track of the score of each player. */
	private int white_score;
	private int black_score;
	
	/** The previous move made by the AI. */
	private int[] lastMove;
	
	/** Initialize a new AI game. */
	public Game(Player color, Difficulty difficulty)
	{
		//Constructor for an AI game
		AI = new team2_AI(color, difficulty);
		boardState = AI.getBoardState();
		white_score = 0;
		black_score = 0;
		lastMove = new int[2];
		lastMove[0] = -1;
		lastMove[1] = -1;
	}
	
	/** Initialize a new LearningAI game. */
	public Game(Player color)
	{
		//Constructor for a LearningAI game
		AI = new team2_LearningAI(color);
		boardState = AI.getBoardState();
		white_score = 0;
		black_score = 0;
		lastMove = new int[2];
		lastMove[0] = -1;
		lastMove[1] = -1;
	}
	
	/** Updates the score variables after a turn. */
	public void updateScore()
	{
		int black = 0;
		int white = 0;
		boardState = AI.getBoardState();
		//counts the number of black and white pieces on the board
		for(int i = 0; i < boardState.length; i++)
		{
			for(int j = 0; j < boardState[i].length; j++)
			{
				if(boardState[i][j] == Player.BLACK)
				{
					black++;
				}
				if(boardState[i][j] == Player.WHITE)
				{
					white++;
				}
			}
		}
		black_score = black;
		white_score = white;
	}
	
	/** Returns true if the conditions for a game over are met (someone won or there are no moves left) */
	public boolean gameOver()
	{
		updateScore();
		
		MinimaxTree AIminimax = (MinimaxTree)AI.minimax;
		Player[][] bsCopy = AIminimax.copy(boardState);
		
		//if neither player can make a move, the game is over
		if(AIminimax.validMoves(bsCopy, Player.WHITE).size() == 0 
			&& AIminimax.validMoves(bsCopy, Player.BLACK).size() == 0 )
			return true;
		
		//if the board is full, the game is over
		if(black_score + white_score == 64)
			return true;
		
		return false;
	}

	//The AI makes its move
	public void makeMove(Player[][] bState)
	{
		//if there is a move to be made
		
		if(AI.makeMove(boardState, lastMove)[0] != -1 && AI.makeMove(boardState, lastMove)[1] != -1){
			lastMove = AI.makeMove(boardState, lastMove);
			boardState = AI.getBoardState();
		}
		else{
			//if there is no move to be made, pass
			boardState = AI.getBoardState();
		}
	}
	
	//Player makes their move
	public void updateMinimax(int[] opponentMove, Player color)
	{
		//Update the minimax tree given the opponent's move
		AI.updateMinimax(opponentMove, color);
		//Adjust difficulty based on opponent's move (LearningAI only)
		AI.adjust(getScore(AI.getPlayer()), getScore(AI.minimax.opposite(AI.getPlayer())));
		//Update the board state
		boardState = AI.getBoardState();
	}
	
	/** Displays the board state in text form. */
	public void disp()
	{
		for(int i = 0; i < boardState.length; i++)
		{
			for(int j = 0; j < boardState[i].length; j++)
			{
				System.out.print(boardState[i][j] + " ");
			}
			System.out.print("\n");
		}
	}
	
	/** Returns the board state. */
	public Player[][] getState()
	{
		return boardState;
	}
	
	/** Retursn the score of the player. */
	public int getScore(Player player)
	{
		updateScore();
		if(player == Player.WHITE)
			return white_score;
		else if(player == Player.BLACK)
			return black_score;
		return -35902823;
	}
	
	/** Called when the game is over - returns the winner or empty if it's a tie */
	public Player winner()
	{
		if(white_score > black_score)
			return Player.WHITE;
		else if(black_score > white_score)
			return Player.BLACK;
		else
			return Player.EMPTY;
	}
	
	/** Accessor for Client that returns a LearningAI cast of the AI */
	public team2_LearningAI getLearningAI()
	{
		return (team2_LearningAI)AI;
	}
}
